import numpy as np


class ManualKNNClassifier:
    def __init__(self, n_neighbors=3):
        """
        初始化手动 KNN 分类器。
        :param n_neighbors: 用于分类的最近邻数量。
        """
        self.n_neighbors = n_neighbors
        self.X_train = None
        self.y_train = None

    def fit(self, X, y):
        """
        训练 KNN 模型。
        :param X: 训练数据，形状为 (n_samples, n_features)。
        :param y: 训练标签，形状为 (n_samples,)。
        """
        self.X_train = np.array(X)
        self.y_train = np.array(y)

    def predict(self, X):
        """
        使用训练数据对给定数据进行预测。
        :param X: 测试数据，形状为 (n_samples, n_features)。
        :return: 预测的标签，形状为 (n_samples,)。
        """
        X = np.array(X)
        predictions = []

        for x in X:
            # 计算所有训练样本与测试样本 x 的欧几里得距离
            distances = np.sqrt(np.sum((self.X_train - x) ** 2, axis=1))

            # 找到最近的 k 个邻居的索引
            nearest_indices = np.argsort(distances)[:self.n_neighbors]

            # 根据最近邻的标签进行投票
            nearest_labels = self.y_train[nearest_indices]
            most_common_label = np.bincount(nearest_labels).argmax()

            predictions.append(most_common_label)

        return np.array(predictions)

    def score(self, X, y):
        """
        计算模型的准确性。
        :param X: 测试数据，形状为 (n_samples, n_features)。
        :param y: 测试标签，形状为 (n_samples,)。
        :return: 准确性得分。
        """
        predictions = self.predict(X)
        return np.mean(predictions == y)